<template>
    <lgDialog :visible="visible" :width="dialogWidth" :title="title || option.title" :headerSlot="headerSlot" @close="onClose" top="10vh">
            <div class="lg-tailor">
                <div class="lg-tailor__tailor" :style="wrapperStyle">
                    <div class="loading" v-show="loading">
                      <i class="iconfont icon-loading"></i>
                      <p>读取中...</p>
                    </div>
                    <vue-cropper
                        ref="cropper"
                        :img="imgSrc || optionImg"
                        :outputSize="option.outputSize || 1"
                        :outputType="imgSrc ? getLinkType(imgSrc) : getLinkType(option.outputType)"
                        :info="option.info || true"
                        :canScale="option.canScale"
                        :autoCrop="option.autoCrop || true"
                        :autoCropWidth="callBackNumerical(option.autoCropWidth || width) + 'px'"
                        :autoCropHeight="callBackNumerical(option.autoCropHeight || height) + 'px'"
                        :fixed="option.fixed"
                        :fixedNumber="option.fixedNumber"
                        :full="option.full"
                        :fixedBox="option.fixedBox"
                        :canMove="option.canMove"
                        :canMoveBox="option.canMoveBox || false"
                        :original="option.original"
                        :centerBox="option.centerBox"
                        :high="option.high"
                        :infoTrue="option.infoTrue"
                        :maxImgSize="option.maxImgSize || 3000"
                        :enlarge="option.enlarge || 1"
                        :mode="option.mode"
                        @imgLoad="imgLoad"
                        >
                    </vue-cropper>
                </div>
                <div class="lg-tailor__button">
                    <lg-button type="primary" plain @click="onOperation('changeScale', 1)" v-if="isScale" icon="icon-magnify" :disabled="loading">放大</lg-button>
                    <lg-button type="primary" plain @click="onOperation('changeScale', -1)" v-if="isScale" icon="icon-lessen" :disabled="loading">缩小</lg-button>
                    <lg-button type="primary" plain @click="onOperation('rotateLeft')" v-if="isScale" icon="icon-leftRotation" :disabled="loading">左旋转</lg-button>
                    <lg-button type="primary" plain @click="onOperation('rotateRight')" v-if="isScale" icon="icon-dextroversion" :disabled="loading">右旋转</lg-button>
                    <lg-button type="success" @click="onTailor" :disabled="loading">确认裁剪</lg-button>
                </div>
            </div>
    </lgDialog>
</template>

<script>
import lgDialog from '@/components/Others/dialog'
import lgButton from '@/components/Basic/button'
import { getUrlFileName, base64toBlob, blobToBase64, imageToBase64  } from '@/libs/index.js'
import { VueCropper } from 'vue-cropper'
export default {
  name:"lgTailor",
  components: { lgDialog, VueCropper, lgButton },
  props: {
    option: {
      type: Object,
      default: () => {
        return {}
      }
    },
    srcArr: {
      type: Array,
      default: () => {
        return []
      }
    },
    width: {
      type: Number,
      default: 600
    },
    height: {
      type: Number,
      default: 300
    },
    scale: {
      type: Number,
      default: 0.8
    },
    title: {
      type: String,
      default: '图片裁剪'
    },
    headerSlot: {
      type: Boolean,
      default: true
    },
    visible: {
      type: Boolean,
      default: false
    },
    isScale: {
      type: Boolean,
      default: true
    },
    isRotate: {
      type: Boolean,
      default: true
    },
    callbackDataType: {
      type: String,
      default: 'base64'
    }

  },
  data () {
    return {
      imgSrc: '',
      optionImg: '',
      accomplishArr: [],
      pageSrcArr: [],
      index: 0,
      type: 'notLoad',
      loading: false  // 添加load组件
    }
  },
  watch: {
    srcArr: {
      handler (newVal) {
        if (!newVal.length) return false
        let blobTransitionBase64Array= []
        let promiseAll = []
        if (typeof newVal[0] != 'string') {
          if (newVal[0] && typeof newVal[0].src == 'string'){
            this.type = 'http'
            this.loading = true
          } else if (Object.prototype.toString.call(newVal[0].src) == '[object File]') {
            this.type = 'blob'
            newVal.forEach(item => {
              let promise = blobToBase64(item.src, item.name).then(res=>{
                blobTransitionBase64Array.push(res)
              })
              promiseAll.push(promise)
            })
          }
        } else {
          this.type = 'http'
          this.loading = true
        }

        if (this.type == 'notLoad' || this.type == 'http') {
            this.pageSrcArr = newVal
            this.transitionInitData(newVal)
        } else if(this.type == 'blob') {
          Promise.all(promiseAll).then(res => {
            this.pageSrcArr = blobTransitionBase64Array
            this.transitionInitData(blobTransitionBase64Array)
          })
        }
      },
      deep: true,
      immediate: true
    },
    option: {
      handler(newVal) {
        if (newVal.img) {
          if (typeof newVal.img == 'string' && newVal.img.includes('data:image/')){
            this.optionImg = newVal.img
          } else if (typeof newVal.img == 'string' && (newVal.img.includes('http://') || newVal.img.includes('https://'))){
            this.loading = true
            this.optionImg = newVal.img
          } else if (Object.prototype.toString.call(newVal.img) == '[object File]'){
            blobToBase64(newVal.img).then(res=>{
              this.optionImg = res
            })
          } else {
            let type = Object.prototype.toString.call(newVal.img)
            throw new Error(`Invalid prop: type check failed for prop "option.img". Expected Object or String, got ${Object.prototype.toString.call(newVal.img).substring(8,type.length - 1)}.`)
          }
        }
      },
      immediate:true,
      deep: true
    }
  },
  computed: {
    dialogWidth () {
      if (this.callBackNumerical(this.option.autoCropWidth || this.width) <= 550) {
        return '550px'
      }
      if (this.callBackNumerical(this.option.autoCropWidth || this.width) >= window.innerWidth) {
        return this.callBackNumerical(this.option.autoCropWidth || this.width) * (this.scale > 1 ? 1 : this.scale < 0 ? 0 :this.scale) + 40 + 'px'
      }
      return this.callBackNumerical(this.option.autoCropWidth || this.width) + 40 + 'px'
    },
    wrapperStyle () {
      let styleObj = {
        width: this.callBackNumerical(this.option.autoCropWidth || this.width) + 'px',
        height: this.callBackNumerical(this.option.autoCropHeight || this.height) + 'px',
        margin: '0 auto'
      }
      if (this.callBackNumerical(this.option.autoCropWidth || this.width) >= window.innerWidth) {
        styleObj.transform = `scale(${this.scale > 1 ? 1 : this.scale < 0 ? 0 :this.scale})`
        styleObj.transformOrigin = 'left top'
      }
      return styleObj
    }
  },
  methods: {
    imgLoad(status) {
      if (status != 'success') {
        this.$message.error('图片读取失败！')
      }
      this.loading = false
    },
    transitionInitData(newVal) {
        let status = newVal.every(item => {
          let key = item.src || item
          return key.includes('data:application/')
        })
        let isHttp = newVal.some(item => {
          let key = item.src || item
          return key.includes('http://') || key.includes('https://')
        })
        //  全部非图片及非http连接图片
        if (status && !isHttp) {
          let newBlobList = []
          newVal.forEach(item => {
            let blob = base64toBlob((item.src || item))
            blob.name = item.name
            newBlobList.push(blob)
          })
          this.$emit('comfirm', newBlobList)
          this.onClose('comfirm')
        } else {
          let index = newVal.findIndex(item => {
            let key = item.src || item
            return key.includes('data:image/')
          })
          if (index > 0) {
            for (let i = 0; i < index; i++) {
              let item = newVal[i]
              let blob = base64toBlob(item.src || item)
              blob.name = item.name
              this.accomplishArr.push(blob)
            }
          }
          this.index = index > -1 ? index : 0
          this.imgSrc = newVal[this.index].src || newVal[this.index]
        }
    },
    onOperation (key, data) {
      this.$refs.cropper[key](data)
    },
    getLinkType (url) {
      if (!url) return 'jpeg'
      let typeString = ''
      let type = ''
      if (url.includes('data:image/')) {
        type = url.includes('data:image/jpg') ? 'jpeg' : url.includes('data:image/png') ? 'png' : 'jpeg'
      } else if (url.includes('data:application/')) {
        type = this.pageSrcArr.length && getUrlFileName(this.pageSrcArr[this.index].name || '') || ''
      } else {
        type = getUrlFileName(url)
      }
      if (type.includes('.jpg') || type.includes('.jpeg') || type.includes('.png')) {
        typeString = type.includes('.jpg') ? 'jpeg' : type != '无法识别文件名' ? type.split('.')[1] : 'jpeg'
      } else {
        typeString = 'jpeg'
      }
      return typeString
    },
    callBackNumerical (val) {
      let number = parseInt(val)
      return number
    },
    onTailor () {
      let key = this.callbackDataType == 'blob' ? 'getCropBlob' : 'getCropData'
      this.$refs.cropper[key](data => {
        // 通过option传入的单个图片
        if (this.pageSrcArr.length == 0 && this.optionImg) {
          let name = typeof this.option.img == 'string' && (this.option.img.includes('http://') || this.option.img.includes('https://')) 
                      ? getUrlFileName(this.option.img)
                        : Object.prototype.toString.call(this.option.img) == '[object File]' ? this.option.img.name  : '未知文件名'
          if ( this.callbackDataType == 'blob') {
            data.name = name
            this.accomplishArr.push(data)
          } else {
            let base64 = {}
            base64.src = data
            base64.name = name
            this.accomplishArr.push(base64)
          }
          this.$emit('comfirm', this.accomplishArr)
          this.onClose('comfirm')
          return false
        }
        let params = null
        if (this.callbackDataType == 'blob') {
          data.name = this.pageSrcArr[this.index].name || getUrlFileName(this.pageSrcArr[this.index].src || this.pageSrcArr[this.index]) || ''
        } else {
          params = {
            name: this.pageSrcArr[this.index].name || getUrlFileName(this.pageSrcArr[this.index].src || this.pageSrcArr[this.index]) || '',
            src: data
          }
        }
        this.accomplishArr.push(params || data)
        let status = this.pageSrcArr[this.index + 1] && this.pageSrcArr[this.index + 1].src ? this.pageSrcArr[this.index + 1].src.includes('data:application/')
                : this.pageSrcArr[this.index + 1] && typeof this.pageSrcArr[this.index + 1] == 'string' ? this.pageSrcArr[this.index + 1].includes('data:application/') : false
        if (status) {
          let item = this.pageSrcArr[this.index + 1]
          if ( this.callbackDataType == 'blob') {
            let blob = base64toBlob(item.src || item)
            blob.name = item.name
            this.accomplishArr.push(blob)
            this.index += 1
          } else {
            let base64 = {}
            base64.src = item.src || item
            base64.name = item.name
            this.accomplishArr.push(base64)
          }
          this.index += 1
        }
        if (this.accomplishArr.length == this.pageSrcArr.length) {
          this.$emit('comfirm', this.accomplishArr)
          this.onClose('comfirm')
          return false
        }
        this.index += 1
        this.imgSrc = this.pageSrcArr[this.index].src || this.pageSrcArr[this.index]
        if (this.type == 'http') {
          this.loading = true
        }
      })

    },
    onClose (status) {
      this.$emit('close', status)
      this.$emit('update:visible', false)
      this.accomplishArr = []
      this.index = 0
      this.imgSrc = ''
      this.type = 'notLoad'
      this.loading = false
      this.pageSrcArr = []
    }
  }
}
</script>

<style lang="less" scoped>
@keyframes myfirst {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(350deg);
  }
}
.lg-tailor{
    user-select: none;
    .lg-tailor__tailor{
        width: 100%;
        height: 310px;
        overflow: hidden;
        position: relative;
        .loading {
          width: 100%;
          height: 100%;
          position: absolute;
          left: 0;
          top: 0;
          z-index: 9900;
          background-color: rgba(0,0,0,.7);
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
          i{
              font-size: 40px;
              color: #fff;
              animation: myfirst 2s linear infinite;
              display:inline-block;
          }
          p{
            margin: 5px 0 0 0;
            padding: 0;
            color: #fff;
            letter-spacing: 1.5px;
            font-size: 14px;
          }
        }
    }
    .lg-tailor__button{
        margin-top: 30px;
        display: flex;
        justify-content: flex-end;
    }
}
</style>
